import os
import time
import csv
# from datetime import
import uuid
import re
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import chardet


class Gantry:
    def __init__(self, file_path, dir_path):
        self.file_path = file_path
        self.dir_path = dir_path
        self.up_gantry = None
        self.down_gantry = None
        self.up_gantry_df = None
        self.down_gantry_df = None

        self.max_speed = 120
        self.dist = None

    def parse_duration(self, duration_str):
        # 匹配分钟和秒
        if pd.isna(duration_str) or duration_str.strip() == '':
            return None
        match = re.match(r'(\d+)m(\d+)s', duration_str)
        if match:
            minutes = int(match.group(1))
            seconds = int(match.group(2))
            total_seconds = minutes * 60 + seconds
            return total_seconds
        else:
            return None

    def get_flow(self, path, time_interval, type_flag=None):
        # 读取CSV文件
        df = pd.read_csv(path, parse_dates=['transtime_up'],
                         date_parser=lambda x: pd.to_datetime(x, format='%Y/%m/%d %H:%M:%S'))
        if type_flag is not None:
            # 筛选特定车辆类型的数据
            df = df[df['feevehicletype'] == type_flag]
        df = df[(df['match_type'] >= 0) & (df['match_type'] <= 2)]
        # 应用函数，将耗时转换为秒
        # df['duration_seconds'] = df['time_diff'].apply(self.parse_duration).dropna()
        # 应用函数，将耗时转换为秒，并过滤掉无效值
        df['duration_seconds'] = df['time_diff'].apply(self.parse_duration)
        # 过滤掉包含空值的行
        df = df.dropna(subset=['duration_seconds'])
        # 根据时间间隔分组，并计算平均速度
        # grouped = df.groupby(pd.Grouper(key='transtime_up', freq=time_interval))['duration_seconds'].mean().reset_index()

        # 根据时间间隔分组并计算平均速度以及每个分组的样本数量
        grouped = (df.groupby(pd.Grouper(key='transtime_up', freq=time_interval))
                   .agg({'duration_seconds': ['mean', 'count']})
                   .reset_index())

        # 重命名列以便更清晰
        grouped.columns = ['transtime_up', 'duration_seconds', 'count']

        # print(grouped)
        # print(type(grouped), type(df))

        return grouped


    def get_all_flow(self, up_path, down_path, time_interval):

        # 读取CSV文件
        df_up = pd.read_csv(up_path, parse_dates=["transtime_up"],
                         date_parser=lambda x: pd.to_datetime(x, format='%Y/%m/%d %H:%M:%S'))
        # 根据时间间隔分组，并计算平均速度
        grouped_up = df_up.groupby(pd.Grouper(key="transtime_up", freq=time_interval))

        # 计算每组中 "time" 列为空和不为空的数量
        result_up = grouped_up.agg({
            "transtime_down": lambda x: x.notna().sum()
        }).assign(
            total_count=lambda x: grouped_up.size()
        )
        result_up = result_up.reset_index()
        np_up = result_up.to_numpy()
        print(result_up)
        # 读取CSV文件
        df_down = pd.read_csv(down_path, parse_dates=["transtime_down"],
                         date_parser=lambda x: pd.to_datetime(x, format='%Y/%m/%d %H:%M:%S'))
        # 根据时间间隔分组，并计算平均速度
        grouped_down = df_down.groupby(pd.Grouper(key="transtime_down", freq=time_interval))

        # 计算每组中 "time" 列为空和不为空的数量
        result_down = grouped_down.agg({
            "transtime_up": lambda x: x.notna().sum()
        }).assign(
            total_count=lambda x: grouped_down.size()
        )
        result_down = result_down.reset_index()
        np_down = result_down.to_numpy()
        print(result_down)

        fieldnames = ['time', 'total_flow', 'up_flow', 'down_flow', 'flow_diff']
        output_file_path = os.path.join(self.dir_path, "all_flow_data1.csv")  # 替换为实际文件路径
        with open(output_file_path, mode='w', newline='', encoding='utf-8') as file:
            writer = csv.DictWriter(file, fieldnames=fieldnames)
            # 写入表头
            writer.writeheader()
            # 写入行数据
            up_num = np_up.shape[0]
            down_num = np_down.shape[0]
            num = min(up_num, down_num)
            rows = []
            for i in range(num):
                up = np_up[i]
                down = np_down[i]
                # 使用字典来构造每一行
                row_dict = {
                    'time': up[0],
                    'total_flow': (up[2] - up[1] + down[2]),
                    'up_flow': up[2],
                    'down_flow': down[2],
                    'flow_diff': (up[2] - down[2])
                }
                rows.append(row_dict)

            writer.writerows(rows)




        # # 指定输出文件路径
        # output_path = 'output.csv'
        #
        # # 保存 DataFrame 为 CSV 文件
        # result.to_csv(output_path, index=False)

        return 1


    def get_files_containing_substring(self, directory, substring):
        file_name = None
        # 遍历指定目录下的所有文件
        for filename in os.listdir(directory):
            # 构建完整的文件路径
            full_path = os.path.join(directory, filename)

            # 检查是否为文件
            if os.path.isfile(full_path):
                # 检查文件名是否包含指定的子字符串
                if substring in filename:
                    print(f"文件名包含 '{substring}' 的文件：{full_path}")
                    file_name = full_path
        return file_name




    def get_match_data(self, path):
        # 使用 chardet 检测文件编码
        with open(path, 'rb') as f:
            result = chardet.detect(f.read(10000))
        detected_encoding = result['encoding']
        # print(f"Detected encoding: {detected_encoding}")

        # 使用检测到的编码读取 CSV 文件
        df = pd.read_csv(path, encoding=detected_encoding)
        # print(df.head())

        # a = df.to_dict(orient='records')
        df_np = df.to_numpy()
        # 获取第五列（索引为 4）
        fifth_column = df_np[:, 5]
        # 找出第五列值大于 0 的条件
        mask = (fifth_column >= 0) & (fifth_column < 3)
        # 使用布尔索引选择满足条件的行
        filtered_arr = df_np[mask]
        return filtered_arr

    # def deal_np_data(self, df_np):
    #
    #     # 找到不包含值2的行
    #     rows_to_keep = ~np.any(df_np == 2, axis=1)
    #     # 使用布尔索引删除指定行
    #     filtered_arr = df_np[rows_to_keep]
    #     time_diff_list = []
    #     for row in filtered_arr:
    #         time_diff = row[4]
    #         # 解析时间差字符串
    #         parts = time_diff.split('m')
    #         fen = int(parts[0])  # 分钟数
    #         miao = int(parts[1].split('s')[0])  # 秒数
    #         # 计算总秒数
    #         seconds = fen * 60 + miao
    #         time_diff_list.append([seconds])
    #     # 假设我们有一个新的列要添加
    #     new_column = np.array(time_diff_list)
    #     arr_with_new_column = np.concatenate((filtered_arr, new_column), axis=1)
    #
    #     return arr_with_new_column


    def get_mean_time(self, df_np):
        total_num = len(df_np)
        # 初始化一个空列表来存储总秒数
        total_seconds = []
        for row in df_np:
            time_diff = row[4]
            # if type(time_diff) != str:
            #     continue
            if int(row[5]) < 0:
                continue
            # 解析时间差字符串
            parts = time_diff.split('m')
            fen = int(parts[0])  # 分钟数
            miao = int(parts[1].split('s')[0])  # 秒数
            # 计算总秒数
            seconds = fen * 60 + miao
            total_seconds.append(seconds)
            if seconds < 0:
                print("time_diff: ", time_diff, row)
        # 将列表转换为 NumPy 数组
        total_seconds_array = np.array(total_seconds)
        # 计算总和
        total_seconds_sum = np.sum(total_seconds_array)
        # 计算平均值
        seconds_average = np.mean(total_seconds_array)
        # 计算最大值
        seconds_max = np.max(total_seconds_array)
        # 计算最小值
        seconds_min = np.min(total_seconds_array)

        print(f"Total seconds: {total_seconds_sum}, seconds_average: {seconds_average}, num: {len(total_seconds)}, "
              f"total_num: {total_num}, max: {seconds_max}, min: {seconds_min}")
        return total_seconds_sum, seconds_average, seconds_max, seconds_min

    def get_vehicle_class_pass_time(self, df_np):
        vehicle_class_pass = {}

        for row in df_np:
            time_diff = row[4]
            # if type(time_diff) != str:
            #     continue
            if int(row[5]) < 0:
                continue
            # 解析时间差字符串
            parts = time_diff.split('m')
            fen = int(parts[0])  # 分钟数
            miao = int(parts[1].split('s')[0])  # 秒数
            # 计算总秒数
            seconds = fen * 60 + miao

            if row[1] not in vehicle_class_pass:
                vehicle_class_pass[row[1]] = {}
                vehicle_class_pass[row[1]]['time_data'] = [seconds]
            else:
                vehicle_class_pass[row[1]]['time_data'].append(seconds)

        for key, value in vehicle_class_pass.items():
            total_seconds_array = np.array(value['time_data'])
            value['sum_time'] = np.sum(total_seconds_array)
            value['mean_time'] = np.mean(total_seconds_array)
            value['num'] = len(total_seconds_array)

        for key, value in vehicle_class_pass.items():
            # 计算平均速度(m/s)
            vehicle_class_pass[key]['speed'] = self.dist / value['mean_time']
            # print(key, value['speed'])

        # print(vehicle_class_pass)

        return vehicle_class_pass

    def get_vlp_speed(self, df_np):
        vlp_speed_dict = {}
        for row in df_np:
            time_diff = row[4]
            # if type(time_diff) != str:
            #     continue
            if int(row[5]) < 0:
                continue
            # 解析时间差字符串
            parts = time_diff.split('m')
            fen = int(parts[0])  # 分钟数
            miao = int(parts[1].split('s')[0])  # 秒数
            # 计算总秒数
            seconds = fen * 60 + miao
            # m/s
            speed = round(self.dist / seconds, 2)
            if speed < 0:
                print("速度为负", speed, self.dist, seconds, row)
            if row[0] not in vlp_speed_dict:
                vlp_speed_dict[row[0]] = {
                    "type": row[1],
                    "speed": [speed],
                    "sum_time": [seconds],
                    "num": 1
                }
            else:
                vlp_speed_dict[row[0]]['speed'].append(speed)
                vlp_speed_dict[row[0]]['sum_time'].append(seconds)
                vlp_speed_dict[row[0]]['num'] += 1

        for vlp, info in vlp_speed_dict.items():
            info['mean_speed'] = round(sum(info['speed']) / info['num'], 2)

        return vlp_speed_dict

    def get_vehicle_data(self, df_np, vehicle_name):
        # 定义条件：第一列等于 "A123"
        condition = df_np[:, 0] == vehicle_name
        # 使用布尔索引获取符合条件的行
        matching_rows = df_np[condition]

        return matching_rows

    def time_speed(self, df_np):
        time_speed_dict = {}
        for row in df_np:
            time_diff = row[4]
            # if type(time_diff) != str:
            #     continue
            if int(row[5]) < 0:
                continue
            # 解析时间差字符串
            parts = time_diff.split('m')
            fen = int(parts[0])  # 分钟数
            miao = int(parts[1].split('s')[0])  # 秒数
            # 计算总秒数
            seconds = fen * 60 + miao
            # m/s
            speed = round(self.dist / seconds, 2)
            if row[2] not in time_speed_dict:
                time_speed_dict[row[2]] = speed

        return time_speed_dict

    def get_vlp_time_csv(self, vlp_speed_dict, filename):
        vlp_time_dict = {}
        for vlp, info in vlp_speed_dict.items():
            vlp_time_dict[vlp] = {
                "type": info['type'],
                "mean_speed": info['mean_speed'],
                "mean_time": sum(info['sum_time']) / info['num'],
                "num": info['num']
            }
            time_list = info['sum_time']
            i = 0
            for time in time_list:
                vlp_time_dict[vlp]["time" + str(i)] = time
                i += 1

        self.save_csv(vlp_time_dict, filename, "vlp")

    def get_vehicle_class_pass_time_csv(self, vehicle_class_data, filename):
        vehicle_class_pass_time = {}
        for key, value in vehicle_class_data.items():
            vehicle_class_pass_time[key] = {
                "sum_time": value['sum_time'],
                "mean_time": value['mean_time'],
                "num": value['num'],
                "mean_speed": value['speed']
            }

        self.save_csv(vehicle_class_pass_time, filename, "type")

        self.show_vlp_time_data(vehicle_class_pass_time)

    def save_csv(self, dict, filename, index):
        # 获取所有可能的列名
        all_keys = set()
        for sub_dict in dict.values():
            all_keys.update(sub_dict.keys())
        # 将嵌套字典扁平化为行数据
        rows = []
        for key, sub_dict in dict.items():
            row = {index: key}  # 添加索引列
            for k, v in sub_dict.items():
                row[k] = v
            rows.append(row)
        # 添加所有可能的列名
        fieldnames = [index] + sorted(all_keys)
        with open(filename, mode='w', newline='', encoding='utf-8') as file:
            writer = csv.DictWriter(file, fieldnames=fieldnames)
            # 写入表头
            writer.writeheader()
            # 写入行数据
            writer.writerows(rows)

    def show_vlp_time_data(self, data):
        # 提取数据
        keys = list(data.keys())
        mean_times = [d['mean_time'] for d in data.values() if 'mean_time' in d]
        # 按照期望的顺序排列 keys
        desired_order = sorted(keys)
        ordered_keys = [key for key in desired_order if key in keys]
        # 创建图形和坐标轴
        fig, ax = plt.subplots()
        # 绘制柱状图
        bar_width = 0.35
        indices = np.arange(len(ordered_keys))
        # 柱状图
        rects = ax.bar(indices, mean_times, bar_width, label='Mean_Time')
        # 使用 ax.bar_label 添加标签
        ax.bar_label(rects, labels=[int(v) for v in mean_times], padding=3)
        # 添加标签和标题
        ax.set_xlabel('Type')
        ax.set_ylabel('Time(s)')
        ax.set_title('Vehicle Type and Time Data')
        ax.set_xticks(indices)
        ax.set_xticklabels(ordered_keys)
        ax.legend()
        # 显示图表
        plt.show()

    # def get_one_type_time_csv(self, df_np, vtype, filename):
    #     for row in df_np:
    #
    #         # if type(time_diff) != str:
    #         #     continue
    #         if int(row[5]) < 0:
    #             continue
    #         time_diff = row[4]
    #         # 解析时间差字符串
    #         parts = time_diff.split('m')
    #         fen = int(parts[0])  # 分钟数
    #         miao = int(parts[1].split('s')[0])  # 秒数
    #         # 计算总秒数
    #         seconds = fen * 60 + miao
    #         total_seconds.append(seconds)
    #         if seconds < 0:
    #             print("time_diff: ", time_diff, row)

    def get_car_data(self, grouped):
        df = grouped.copy()
        df["mean_speed"] = df.apply(lambda x: round(self.dist / x['duration_seconds'], 2), axis=1)

        # print(df)
        output_file_path = os.path.join(self.dir_path, "car_time_data1.csv")  # 替换为实际文件路径
        df[['transtime_up', 'duration_seconds', 'mean_speed', 'count']].to_csv(
            output_file_path, index=False, encoding='utf-8')

        return df

    def get_slow_vehicle(self, all_path, time_interval):

        # 读取CSV文件
        df = pd.read_csv(all_path, parse_dates=["transtime_up"],
                         date_parser=lambda x: pd.to_datetime(x, format='%Y/%m/%d %H:%M:%S'))

        # 筛选特定车辆类型的数据
        df = df[df['feevehicletype'] == 1]
        df = df[(df['match_type'] >= 1) & (df['match_type'] <= 2)]
        # 应用函数，将耗时转换为秒，并过滤掉无效值
        df['duration_seconds'] = df['time_diff'].apply(self.parse_duration)
        # # 过滤掉包含空值的行
        # df = df.dropna(subset=['duration_seconds'])

        # 根据时间间隔分组，并计算平均速度
        grouped = df.groupby(pd.Grouper(key='transtime_up', freq=time_interval)).size().reset_index(name='count')
        result = grouped.reset_index()
        np_up = result.to_numpy()
        # print(np_up)


        fieldnames = ['time', 'count']
        output_file_path = os.path.join(self.dir_path, "car_slow_move_data.csv")  # 替换为实际文件路径
        with open(output_file_path, mode='w', newline='', encoding='utf-8') as file:
            writer = csv.DictWriter(file, fieldnames=fieldnames)
            # 写入表头
            writer.writeheader()
            # 写入行数据
            up_num = np_up.shape[0]
            num = up_num
            rows = []
            for i in range(num):
                up = np_up[i]
                # 使用字典来构造每一行
                row_dict = {
                    'time': up[1],
                    'count': up[2],
                }
                rows.append(row_dict)

            writer.writerows(rows)



    def run(self):
        up_path = self.get_files_containing_substring(self.dir_path, 'up')
        down_path = self.get_files_containing_substring(self.dir_path, 'down')
        all_path = self.get_files_containing_substring(self.dir_path, 'all')


        # 获取合并后数据的numpy数组
        df_np = self.get_match_data(all_path)

        # 计算总间隔时长，平均间隔时长， 最大间隔时长，最小间隔时长
        total_seconds_sum, seconds_average, seconds_max, seconds_min = self.get_mean_time(df_np)
        print("最小间隔时长: ", seconds_min)

        # 估算区间距离(米)
        self.dist = round(self.max_speed / 3.6 * seconds_min, 2)
        print("估算区间距离(米): ", self.dist)

        # # 小客车全天通行时间/平均车速分布（最小通行时间的二分之一，取整）
        # time_interval = str(int(seconds_average / 60 * 2)) + 'T'
        # grouped = self.get_flow(all_path, time_interval=time_interval, type_flag=1)
        # self.get_car_data(grouped)
        #
        # retur = self.get_all_flow(up_path, down_path, time_interval=time_interval)

        a = self.get_slow_vehicle(all_path, "10T")

        # if self.dist is not None and self.dist > 0:
        #     # 车型：{"time_data": [], "sum_time": float, "mean_time": float, "num": int, "speed": float}
        #     vehicle_class_data = self.get_vehicle_class_pass_time(df_np)
        #     filename1 = r'..\output\vehicle_class_pass_time.csv'
        #     self.get_vehicle_class_pass_time_csv(vehicle_class_data, filename1)
        #
        #     # 车牌-车速
        #     vlp_speed_dict = self.get_vlp_speed(df_np)
        #     filename2 = r'..\output\vlp_time.csv'
        #     self.get_vlp_time_csv(vlp_speed_dict, filename2)










            # # 异常判断
            # abnormal_data = []
            # for vlp, info in vlp_speed_dict.items():
            #     vtype = info["type"]
            #     mean_speed = info["mean_speed"]
            #     num = info["num"]
            #     vclass_speed = vehicle_class_data[vtype]["speed"]
            #     if mean_speed * 10.0 <= vclass_speed:
            #         matching_rows = self.get_vehicle_data(df_np, vlp)
            #         print("异常数据", vlp, vtype, mean_speed, vclass_speed, matching_rows)
            #         # print(matching_rows)



if __name__ == '__main__':
    # 没用
    file_path = r'D:\GJ\项目\事故检测\邻垫高速事故当日门架流水明细\G004251001000210010,G004251001000310010-20240101.csv'
    # file_path = r'D:\GJ\项目\事故检测\邻垫高速事故当日门架流水明细\G004251001000110010,G004251001000210010-20240531.csv'
    # file_path = r'D:\GJ\项目\事故检测\邻垫高速事故当日门架流水明细\G004251001000310010,G004251002000610010-20240503.csv'
    # file_path = r'D:\GJ\项目\事故检测\邻垫高速事故当日门架流水明细\G004251002000620010,G004251001000320010-20240207.csv'
    dir_path = r'D:\GJ\项目\事故检测\output\G004251002000620010,G004251001000320010-20240131'
    # dir_path = r'D:\GJ\项目\事故检测\output\G004251002000620010,G004251001000320010-20240207'
    # dir_path = r'D:\GJ\项目\事故检测\output\G004251002000620010,G004251001000320010-20240219'


    gantry = Gantry(file_path, dir_path)
    gantry.run()

